package com.ymy.thinking.in.spring.bean.definition;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import thinking.in.spring.ioc.overview.domain.User;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.math.BigDecimal;

/**
 * 什么是 {@link org.springframework.beans.factory.config.BeanDefinition}
 *
 * @author Ringo
 * @date 2021/8/28 22:58
 */
@Configuration
public class WhatIsBeanDefinitionDemo {

    public static void main(String[] args) throws InterruptedException {
        // 创建 IoC 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 包扫描
        applicationContext.scan("com.ymy.thinking.in.spring.bean.definition.**");

        // 创建 BeanDefinition
        BeanDefinition productBeanDefinition = createBeanDefinition();
        // 将 BeanDefinition 注册到 IoC 容器
        applicationContext.registerBeanDefinition("product", productBeanDefinition);

        // 开启 Spring 应用上下文
        applicationContext.refresh();

        // 依赖查找
        Product product = applicationContext.getBean(Product.class);
        System.out.println(product);

        // 关闭 Spring 应用上下文
        applicationContext.close();
    }


    public static BeanDefinition createBeanDefinition() {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Product.class);
        builder
                // 设置属性
                .addPropertyValue("name", "电脑")
                .addPropertyValue("price", new BigDecimal("6800.50"))
                // 依赖注入
                .setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE)
                .addAutowiredProperty("user")
                // 初始化 和 销毁 Bean 的方法
                .setInitMethodName("init")
                .setDestroyMethodName("destroyMethod");
        return builder.getBeanDefinition();
    }


    private static class Product implements InitializingBean, DisposableBean {
        private String name;
        private BigDecimal price;
        private User user;

        @PostConstruct
        public void postConstruct() {
            System.out.println("@PostConstruct...");
        }

        @PreDestroy
        public void preDestroy() {
            System.out.println("@PreDestroy...");
        }

        public void init() {
            System.out.println("Product init...");
        }

        public void destroyMethod() {
            System.out.println("Product destroy..");
        }

        @Override
        public String toString() {
            return "Product{" +
                    "name='" + name + '\'' +
                    ", price=" + price +
                    ", user=" + user +
                    '}';
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public BigDecimal getPrice() {
            return price;
        }

        public void setPrice(BigDecimal price) {
            this.price = price;
        }

        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("afterPropertiesSet...");
        }

        @Override
        public void destroy() throws Exception {
            System.out.println("destroy....");
        }
    }
}
